python函数

python函数的作用、定义、传参、使用。以及递归函数,匿名函数等。

函数的作用

把一段代码封装成一个语法单元中,可以实现代码复用,使程序结构更清晰,方便维护、扩展。

函数的定义&使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'''
def < 函数名>(< 参数(0 个或多个)>) :
< 函数体>
return < 返回值(0 个或多个)>

默认情况下,参数不需要类型声明
默认情况下,函数返回值不需要类型声明
参数和返回值可以为0个或多个,return多个值时返回一个元组
'''

#函数的定义
def fact(n) :
s = 1
for i in range (1, n+1):
s *= i
return s

#函数的调用方式一
ret = fact(10)

#函数的调用方式二
func = fact
ret = func(10)

函数的参数传递

1
2
3
4
5
6
7
8
9
10
# 位置传递,名称传递
def fact(n, m):
s = 1
for i in range (1, n+1):
s *= i
return s//m


fact(10, 5) # 位置传递,按顺序
fact(m=5, n=10) # 名称传递,按名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 可选参数传递
# 可选参数:函数为某些参数指定默认值,构成可选参数
# 可选参数,放最后
'''
def < 函数名> (< 非可选参数, >, <可选参数>):
< 函数体>
return < 返回值>
'''
def fact(n, m=1 ) :
s = 1
for i in range (1, n+1):
s *= i
return s//m

fact( 10)
fact( 10, 5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 可变参数传递
# 可变参数:函数可以接受不确定总数的参数变量

# 元组形式 所有可变参数作为一个元组变量
'''
def <函数名>(<参数>, *b ) :
<函数体>
return <返回值>
'''
def fact(n , *b) :
s = 1
for i in range (1, n+1):
s *= i
for item in b:
s *= item
return s

fact(10,3) # b = (3,)
fact(10,3,5,8) # b = (3,5,8)


# 字典形式
'''
def <函数名>(<参数>, **d ) :
<函数体>
return <返回值>
'''
def fact(n , **d) :
s = 1
for i in range (1, n+1):
s *= i
for item in d:
s *= d[item]
return s

fact(10,a=3) # d = {a:3}
fact(10,a=3,b=5,c=8) # d = {a:3,b:5,c:8}

递归函数

函数定义中调用函数自身的方式

  • 链条:计算过程存在递归链条
  • 基例:存在一个或多个不需要再次递归的基例

递归的实现:函数+分支结构

  • 递归本身是一个函数,需要函数定义方式描述
  • 函数内部,采用分支语句对输入参数进行判断
  • 基例和链条,分别编写对应代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# n的阶乘
def fact(n):
if n == 0:
return 1
else:
return n*fact(n-1)

# 字符串反转
def rvs(s):
if s == '':
return s
else:
return res(s[1:])+s[0]

# 斐波那契数列
f(n) = f(n+1) + f(n+2)
def f(n):
if n == 1 or n == 2:
return 1
else:
return f(n-1) + f(n-2)

# 汉诺塔
def move(n, a, b, c):
if n == 1:
print('move', a, '-->', c)
else:
move(n-1, a, c, b)
move(1, a, b, c)
move(n-1, b, a, c)

move(4, 'A', 'B', 'C')
# 快速排序

使用递归函数需要注意防止栈溢出。

解决递归调用栈溢出的方法是通过尾递归优化,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

1
2
3
4
5
6
7
def fact(n):
return fact_iter(n, 1)

def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)

尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

lambda函数(匿名函数)

用于定义简单的、能够在一行内表示的函数

使用lambda保留字定义,返回函数对象(与def定义的函数对象一毛一样)

1
2
3
4
5
6
7
8
9
10
11
12
# < 函数名> = lambda < 参数>: < 表达式>
# 等价于
'''
def < 函数名>(< 参数>) :
< 函数体>
return < 返回值>
'''

# 定义一个求和函数
f = lambda x, y : x + y
# 调用匿名函数
f (10, 15) # 25
1
2
3
4
5
6
7
8
9
10
'''练习 用lambda打印helloWorld'''
b = lambda :print('helloWorld')

'''练习 实现加法的匿名函数'''
add = lambda x,y:x+y
assert add(1,5)==6

'''练习 实现不定参数的加法'''
myAdd = lambda *x:sum(x)
assert myAdd(1,5,4)==10